package com.live.stamp.base.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.live.stamp.base.service.ISqlDao;
import com.live.stamp.base.service.SqlDao;
import com.live.stamp.base.service.impl.BaseSupportDaoImpl;
import com.live.stamp.base.service.impl.SqlBaseSupportDaoImpl;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;

import javax.sql.DataSource;
import java.sql.SQLException;

@Configuration
@EnableTransactionManagement
public class DefaultDatabaseConfiguration implements TransactionManagementConfigurer {
	private static final Logger logger = LoggerFactory.getLogger(DefaultDatabaseConfiguration.class);
	
	@Value("${spring.datasource.url}")
	private String url;
	
	@Value("${spring.datasource.username}")
	private String username;
	
	@Value("${spring.datasource.password}")
	private String password;
	
	@Value("${spring.datasource.initialSize}")
	private int initialSize;
	
	@Value("${spring.datasource.minIdle}")
	private int minIdle;
	
//	@Value("${spring.datasource.maxIdle}")
//	private int maxIdle;
	
	@Value("${spring.datasource.maxActive}")
	private int maxActive;
	
	@Value("${spring.datasource.maxWait}")
	private int maxWait;
	
	@Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
	private int timeBetweenEvictionRunsMillis;
	
	@Value("${spring.datasource.minEvictableIdleTimeMillis}")
	private int minEvictableIdleTimeMillis;
	
	@Value("${spring.datasource.testWhileIdle}")
	private boolean testWhileIdle;
	
	@Value("${spring.datasource.testOnBorrow}")
	private boolean testOnBorrow;
	
	@Value("${spring.datasource.testOnReturn}")
	private boolean testOnReturn;
	
	@Value("${spring.datasource.removeAbandoned}")
	private boolean removeAbandoned;
	
	@Value("${spring.datasource.removeAbandonedTimeout}")
	private int removeAbandonedTimeout;
	
	@Value("${spring.datasource.poolPreparedStatements}")
	private boolean poolPreparedStatements;
	
	@Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")
	private int maxPoolPreparedStatementPerConnectionSize;
	
	@Value("${spring.datasource.filters}")
	private String filters;
	
	@Value("${spring.datasource.dialect}")
	private String dialect;
	
    private PlatformTransactionManager txManager;
    
	@SuppressWarnings("deprecation")
	@Bean(initMethod="init",destroyMethod="close")
	public DataSource defaultDataSource(){
		DruidDataSource defaultDataSource = new DruidDataSource();
		try{
			//druidDataSource.setDriverClassName(driver);
			defaultDataSource.setUrl(url);
			defaultDataSource.setUsername(username);
			defaultDataSource.setPassword(password);
			defaultDataSource.setInitialSize(initialSize);
			defaultDataSource.setMinIdle(minIdle);
//			defaultDataSource.setMaxIdle(maxIdle);
			defaultDataSource.setMaxActive(maxActive);
			defaultDataSource.setMaxWait(maxWait);
			defaultDataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
			defaultDataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
			defaultDataSource.setTestWhileIdle(testWhileIdle);
			defaultDataSource.setTestOnBorrow(testOnBorrow);
			defaultDataSource.setTestOnReturn(testOnReturn);
			defaultDataSource.setRemoveAbandoned(removeAbandoned);
			defaultDataSource.setRemoveAbandonedTimeout(removeAbandonedTimeout);
			defaultDataSource.setPoolPreparedStatements(poolPreparedStatements);
			defaultDataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
			defaultDataSource.setFilters(filters);
		}catch(SQLException e){
			logger.error("数据库连接池初始化失败", e);
		}
		return defaultDataSource;
	}

	@Bean
	public PlatformTransactionManager defaultTxManager(@Autowired @Qualifier("defaultDataSource") DataSource dataSource) {
	        return new DataSourceTransactionManager(dataSource);
	}
	
	public PlatformTransactionManager annotationDrivenTransactionManager() {
		return txManager;
	}
	
	@Bean
	public SqlSessionFactory sqlSessionFactory(@Autowired @Qualifier("defaultDataSource") DataSource defaultDataSource) throws Exception {
		    SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
	        sessionFactory.setDataSource(defaultDataSource);
	        sessionFactory.setFailFast(true);
	        sessionFactory.setConfigLocation(new ClassPathResource("/config/sql-map-config.xml"));
	        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:/sql/**/ibatis-*.xml"));
	        return sessionFactory.getObject();
	}
	
	@Bean
	public SqlSessionTemplate defaultSqlSessionTemplate(@Autowired @Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory)throws Exception {
		return new SqlSessionTemplate(sqlSessionFactory);
	}
	
	@Bean
	public ISqlDao defaultSqlDao(@Autowired @Qualifier("defaultDataSource") DataSource defaultDataSource) throws Exception {
		return new SqlBaseSupportDaoImpl(defaultDataSource,dialect);
	}
	
}
